home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
BBS in a Box 7
/
BBS in a Box - Macintosh - Volume VII (BBS in a Box) (January 1993).iso
/
Files
/
Hyper
/
Q-R
/
REgion.cpt
/
Region Buttons
/
card_9446.txt
< prev
next >
Wrap
Text File
|
1987-11-07
|
12KB
|
360 lines
-- card: 9446 from stack: in
-- bmap block id: 0
-- flags: 0000
-- background id: 3256
-- name: Source Code
-- part contents for background part 1
----- text -----
{$R-}
{**************************************************************************
Button Regions
by Keith Rollin
October, 1987
© Apple Computer, Inc.
All Rights Reserved
This XCMD is an example of how to implement buttons in HyperCard that
are shaped as regions. This is facilitated by the use of 3 commands:
NewRgn - Create the buttons, draws them on the screen, passes
a handle back to the HyperCard script.
TestHit - Tests the buttons against the mouse location. Returns
the number of the button hit, or zero if none.
DisposeRgn - Removes the button descriptions from memory. MUST be
called before the stack is left.
***************************************************************************}
{$S ButtonRgn } { Segment name must be the same as the command name. }
UNIT DummyUnit;
INTERFACE
USES {$Load Rgn.sym} MemTypes, QuickDraw, OSIntf, ToolIntf, HyperXcmd;
PROCEDURE ENTRYPOINT(paramPtr: XCmdPtr);
{
***************************************************************************
}
IMPLEMENTATION
CONST
NUMBER_OF_BUTTONS = 4;
TYPE
Str31 = String[31];
RgnArray = ARRAY [1..1] OF RgnHandle;
ArrayPtr = ^RgnArray;
ArrayHandle = ^ArrayPtr;
{***************************************************************************
This arcane sequence of instructions is required for any sort of
'vanilla' code resource that doesn't have a jump table. For things
like FKEYs, INITs, and XCMDs, the entry point must be at the beginning
of the resource.
***************************************************************************}
PROCEDURE ButtonRgn(paramPtr: XCmdPtr);
FORWARD;
PROCEDURE ENTRYPOINT(paramPtr: XCmdPtr);
BEGIN
ButtonRgn(paramPtr);
END;
PROCEDURE ButtonRgn(paramPtr: XCmdPtr);
VAR
flashCount: LongInt;
i: INTEGER;
port: GrafPtr;
str: Str255;
{$I XCmdGlue.inc }
{***************************************************************************
ParmStr - Returns the nth parameter passed to the XCMD in string form
***************************************************************************}
FUNCTION ParmStr(parmnum: INTEGER): Str255; {return text of parm#}
VAR
str: Str255;
BEGIN
ZeroToPas(paramPtr^.params[parmnum]^, str);
ParmStr := str;
END;
{***************************************************************************
ParmVal - Returns the nth parameter passed to the XCMD in numeric form
***************************************************************************}
FUNCTION ParmVal(parmnum: INTEGER): LongInt;
VAR
str: Str255;
tHandle: handle;
BEGIN
tHandle := EvalExpr(ParmStr(parmnum)); {evaluate the string}
ZeroToPas(tHandle^, str); {convert the [string] value to a longint}
ParmVal := StrToNum(str);
DisposHandle(tHandle);
END;
{***************************************************************************
NewButton - Responsible for the creation of all the buttons. Accepts
as input the button number to create, and returns a RgnHandle to that
button.
***************************************************************************}
FUNCTION NewButton(buttonNum: INTEGER): RgnHandle;
VAR
tRgn, tRgn2: RgnHandle;
tRect: rect;
BEGIN
CASE buttonNum OF
1: BEGIN
tRgn := NewRgn;
OpenRgn;
SetRect(tRect, 72, 164, 152, 215);
FrameRect(tRect);
CloseRgn(tRgn);
END;
2: BEGIN
tRgn := NewRgn;
OpenRgn;
SetRect(tRect, 240, 165, 359, 213);
FrameOval(tRect);
CloseRgn(tRgn);
END;
3: BEGIN
tRgn := NewRgn;
OpenRgn;
SetRect(tRect, 146, 224, 200, 284);
FrameRoundRect(tRect, 16, 16);
CloseRgn(tRgn);
tRgn2 := NewRgn;
OpenRgn;
MoveTo(173, 270);
LineTo(156, 305);
LineTo(190, 305);
LineTo(173, 270);
CloseRgn(tRgn2);
UnionRgn(tRgn, tRgn2, tRgn);
DisposeRgn(tRgn2);
END;
4: BEGIN
tRgn := NewRgn;
OpenRgn;
MoveTo(337, 230);
LineTo(280, 290);
LineTo(394, 290);
LineTo(337, 230);
SetRect(tRect, 280, 230, 300, 250);
FrameRect(tRect);
SetRect(tRect, 374, 230, 394, 250);
FrameRect(tRect);
CloseRgn(tRgn);
END;
END;
NewButton := tRgn;
END;
{***************************************************************************
doNewRgn - Creates a handle to an array of handles large enough to hold
NUMBER_OF_BUTTONS region handles. Then calls NewButton NUMBER_OF_BUTTONS
times to fetch the handles to each button. Draws the buttons to the
screen and returns the handle to the array in a specified global
variable.
***************************************************************************}
PROCEDURE doNewRgn; {Create a New set of region(s) and plot them}
VAR
ButtonPict: PicHandle;
result: LongInt;
tHandle: handle;
str: Str255;
MyArray: ArrayHandle;
BigRect: rect;
i: INTEGER;
BEGIN
{ Create all the buttons, and store their handles in MyArray }
MyArray := ArrayHandle(NewHandle(NUMBER_OF_BUTTONS * 4));
HLock(handle(MyArray));
FOR i := 1 TO NUMBER_OF_BUTTONS DO BEGIN
MyArray^^[i] := NewButton(i);
END;
{ Get a rectangle that includes all the buttons.}
BigRect := MyArray^^[1]^^.rgnBBox;
IF i > 1 THEN
FOR i := 2 TO NUMBER_OF_BUTTONS DO BEGIN
UnionRect(BigRect, MyArray^^[i]^^.rgnBBox, BigRect);
END;
{ Create a picture that plots all the buttons }
ButtonPict := OpenPicture(BigRect);
FOR i := 1 TO NUMBER_OF_BUTTONS DO BEGIN
FrameRgn(MyArray^^[i]);
END;
ClosePicture;
{Put the picture on the Clipboard for HyperCard to find}
HLock(handle(ButtonPict));
result := ZeroScrap;
result := PutScrap(GetHandleSize(handle(ButtonPict)), 'PICT',
ptr(ButtonPict^));
HUnlock(handle(ButtonPict));
KillPicture(ButtonPict);
IF result <> noErr THEN BEGIN
paramPtr^.returnValue := PasToZero('Error: Creating buttons');
DisposHandle(handle(MyArray));
END
ELSE BEGIN
SendCardMessage('Type "V" with commandkey');
SendCardMessage('Choose browse tool');
ZeroToPas(paramPtr^.params[1]^, str);
tHandle := PasToZero(LongToStr(LongInt(MyArray)));
SetGlobal(str, tHandle);
DisposHandle(tHandle);
HUnlock(handle(MyArray));
END;
END;
{***************************************************************************
doTestHit - Accepts a mouse location and optional boolean value. The
mouse location is checked against all the button regions for a hit. If
there is a hit, the button number is returned in 'the result'. If there
is no hit, button number zero is returned. The optional boolean value
determines whether or not the button is hilighted when hit. If the
booleam value is not specified, then it defaults to FALSE.
***************************************************************************}
PROCEDURE doTestHit;
VAR
mouseLoc: point;
MyArray: ArrayHandle;
ButtonPict: PicHandle;
result: LongInt;
str: Str255;
hit: boolean;
BEGIN
{Get the mouse location and data handle}
mouseLoc.h := ParmVal(3);
mouseLoc.v := ParmVal(4);
MyArray := ArrayHandle(ParmVal(1));
HLock(handle(MyArray));
{loop to see if the mouseloc falls into any regions}
i := 0;
hit := FALSE;
REPEAT
i := i + 1;
hit := PtInRgn(mouseLoc, MyArray^^[i]);
UNTIL (i = NUMBER_OF_BUTTONS) OR hit;
{It does, so return the button number, and hilight it if necessary}
IF hit THEN BEGIN
paramPtr^.returnValue := PasToZero(NumToStr(i)); {return button#}
IF paramPtr^.paramcount = 5 THEN BEGIN {do highlighting?}
ZeroToPas(paramPtr^.params[5]^, str);
IF StrToBool(str) THEN BEGIN {yes, do the hilighting}
HLock(handle(MyArray^^[i]));
ButtonPict := OpenPicture(MyArray^^[i]^^.rgnBBox);
InvertRgn(MyArray^^[i]);
ClosePicture;
result := ZeroScrap;
result := PutScrap(GetHandleSize(handle(ButtonPict)), 'PICT',
ptr(ButtonPict^));
KillPicture(ButtonPict);
HUnlock(handle(MyArray^^[i]));
HUnlock(handle(MyArray)); {don't need this locked anymore}
IF result = noErr THEN BEGIN
SendCardMessage('type "V" with commandkey');
{ There may be a problem with the above step. If you
have a measly 1 meg, there may not be enough memory
for HyperCard to use the painting tools. It will
get into a viscous loop, complaining that there
is not enough room, until crashing with an ID=28. I
was able to relieve the problem by unlocking the
handle to MyArray 3 lines up instead of at the end of
the procedure, but it still indicates that there is
very little room left when painting.}
SendCardMessage('type "Z" with commandkey');
SendCardMessage('choose browse tool');
END; {if picture was create OK}
END; {if param[5] = TRUE}
END; {if paramcount = 5}
END {if PtInRgn}
ELSE BEGIN
paramPtr^.returnValue := PasToZero('0')
END;
HUnlock(handle(MyArray));
END;
{***************************************************************************
doDispose - Removes the buttons from memory. Loops through the array
of region handles, removing them one by one. Then disposes the handle
to that array.
***************************************************************************}
PROCEDURE doDispose;
VAR
MyArray: ArrayHandle;
i: INTEGER;
BEGIN
MyArray := ArrayHandle(ParmVal(1));
HLock(handle(MyArray));
IF (MyArray <> NIL) THEN BEGIN
FOR i := 1 TO NUMBER_OF_BUTTONS DO BEGIN
DisposeRgn(MyArray^^[i]);
END;
DisposHandle(handle(MyArray));
SendCardMessage(concat('put empty into ', ParmStr(1)));
END;
END;
{***************************************************************************
Main Routine - Checks the second parameter to see what routine to
call and calls it.
***************************************************************************}
BEGIN
ZeroToPas(paramPtr^.params[2]^, str);
IF StringEqual(str, 'NewRgn') THEN
doNewRgn
ELSE IF StringEqual(str, 'TestHit') THEN
doTestHit
ELSE IF StringEqual(str, 'DisposeRgn') THEN doDispose;
END;
END.
-- part contents for background part 9
----- text -----
98